; *******************************************************************
;   gobj_form.ahk
; *******************************************************************

; -------------------------------------------------------------------
;   includes
; -------------------------------------------------------------------

; #include filex.ahk                            

; -------------------------------------------------------------------
;   gobj_font
; -------------------------------------------------------------------

class gobj_font
{
  __New(form_or_name="", size="", color="", weight="")
  {
    if (isObject(form_or_name))
    {
      this.form := form_or_name
    }
    else
    {
      this["name"]   := form_or_name
      this["size"]   := size
      this["color"]  := color
      this["weight"] := weight
    }
  }

  __Set(aName, aValue)
  {
    if (aName = "name")
    {
      if (isObject(this.form))
      {
        this.form.__Set("font", aValue)
        return aValue
      }
    }
    if (aName = "size")
    {
      if (isObject(this.form))
      {
        this.form.setFont("", "s" . aValue)
        return aValue
      }
    }
    if (aName = "color")
    {
      if (isObject(this.form))
      {
        this.form.setFont("", "c" . aValue)
        return aValue
      }
    }
    if (aName = "weight")
    {
      if (isObject(this.form))
      {
        this.form.setFont("", "w" . aValue)
        return aValue
      }
    }
    if aName in bold,italic,strike,underline,norm
    {
      if (isObject(this.form))
      {
        if (aValue)
          this.form.setFont("", aName)
        return aValue
      }
    }
  }
}

; -------------------------------------------------------------------
;   gobj_Size
; -------------------------------------------------------------------

class gobj_Size
{
  __New(form_or_w="", type_or_h="")
  {
    if (isObject(form_or_w))
    {
      this.form := form_or_w
      this.type := type_or_h
    }
    else
    {
      if form_or_w is integer
        this["w"] := form_or_w
      else if (form_or_w != "")
        this["sizestr"] := form_or_w
      if type_or_h is integer
        this["h"] := type_or_h
    }
  }
  
  __Set(aName, aValue)
  {
    if (aName = "w")
    {
      if (isObject(this.form))
      {
        this.form.__Set(this.type, aValue . "x")
        return aValue
      }
    }
    if (aName = "h")
    {
      if (isObject(this.form))
      {
        this.form.__Set(this.type, "x" . aValue)
        return aValue
      }
    }
  }
}

; -------------------------------------------------------------------
;   gobj_form
; -------------------------------------------------------------------

class gobj_form
{
  _priv_  := {  GuiName:      "MainForm"
              , controls:     {} }
  	  

  ; -----------------------------------------------------------------
  ;   __New
  ; -----------------------------------------------------------------

  __New()
  {
  }

  _init_pre()
  {
    p := {}
    this.Insert("_priv_", p)
    this._priv_.GuiName     := "MainForm"
    this._priv_.controls    := {}
    this._priv_.precreate  := {}
    this._priv_.precreate.properties  := []
    this._priv_.precreate.items       := []
    this._priv_.precreate.controls    := {}
  }
  
  _init_post()
  {
    for k, v in this._priv_.precreate.items
    {
      this[v.name] := v.value    
    }
  }
  
  ; -----------------------------------------------------------------
  ;   __Set
  ; -----------------------------------------------------------------

  __Set(aName, aValue)
  {
    if aName in _priv_
    {
      this._init_pre()
      return aValue
    }
    
    if (aValue.HasKey("_priv_"))
    {
      if (aValue._priv_.HasKey("form"))
      {
        if (this._priv_.HasKey("GuiNameAssigned"))
        {
          this._priv_.controls.Insert(aName, aValue)
          aValue.OnInsertControl(this, aName)
        }
        else
        {
          item := {}
          item.name  := aName
          item.value := aValue
          this._priv_.precreate.items.Insert(item)
          this._priv_.precreate.controls.Insert(aName, aValue)
        }
        return aValue
      }
    }

    if aName in x,y,w,h,text
    {
      formid := this.getID()
      Gui %formid%:+LastFound
      WinGetPos X, Y, W, H
      if (aName = "x")
        X := aValue
      if (aName = "y")
        Y := aValue
      if (aName = "w")
        W := aValue
      if (aName = "h")
        H := aValue
      if (aName = "text")
        WinSetTitle %aValue%
      else
        WinMove,,, %X%, %Y%, %W%, %H%
      return aValue
    }

    option_items := "AlwaysOnTop,Border,Caption,Disabled"
    option_items .= ",LastFound,LastFoundExist,MaximizeBox,MinimizeBox"
    option_items .= ",OwnDialogs,Resize,SysMenu,Theme,ToolWindow"
    if aName in %option_items%
    {
      formid := this.getID()
      val_char := "+"
      if not aValue
      {
        val_char := "-"
      }
      Gui %formid%:%val_char%%aName%
      return aValue
    }

    if aName in MinSize,MaxSize
    {
      formid := this.getID()
      if (!isObject(aValue))
      {
        Gui %formid%:+%aName%%aValue%
        return aValue
      }
      else
      {
        if (aValue.HasKey("sizestr"))
          sizestr := aValue.sizestr
        else
          sizestr := aValue.w . "x" . aValue.h 
        Gui %formid%:+%aName%%sizestr%
        return aValue
      }
    }

    if aName in font
    {
      formid := this.getID()
      if (!isObject(aValue))
      {
        Gui %formid%:%aName%,,%aValue%
        return aValue
      }
      else
      {
        fontoptstr := ""
        if (aValue.size != "")
          fontoptstr := fontoptstr . " s" . aValue.size
        if (aValue.color != "")
          fontoptstr := fontoptstr . " c" . aValue.color
        if (aValue.weight != "")
          fontoptstr := fontoptstr . " w" . aValue.weight
        fontname := aValue.name
        Gui %formid%:%aName%,%fontoptstr%,%fontname%
        return aValue
      }
    }
  }

  ; -----------------------------------------------------------------
  ;   __Get
  ; -----------------------------------------------------------------

  __Get(aName)
  {
    if aName in MinSize,MaxSize
    {
      if (!this.HasKey("m_" . aName))
        this["m_" . aName] := new gobj_Size(this, aName)
      return this["m_" . aName]
    }

    if aName in font
    {
      if (!this._priv_.HasKey(aName))
        this._priv_[aName] := new gobj_font(this)
      return this._priv_[aName]
    }

    if (this._priv_.controls.HasKey(aName))
    {
      return this._priv_.controls[aName]
    }

    if (this._priv_.precreate.controls.HasKey(aName))
    {
      return this._priv_.precreate.controls[aName]
    }
  }

  ; -----------------------------------------------------------------
  ;   OnCommand
  ; -----------------------------------------------------------------

  OnCommand(form, control)
  {
    cntl := SubStr(control, StrLen(form)+2)
    if (this._priv_.controls.HasKey(cntl))
      this._priv_.controls[cntl].OnCommand.(this)
  }

  ; -----------------------------------------------------------------
  ;   OnSize
  ; -----------------------------------------------------------------

  OnSize(w, h)
  {
    this.LastFound := true
    for k, v in this._priv_.controls
      v.OnSize(w, h)
    WinGet hwnd, ID
    DllCall("RedrawWindow", "UInt", hwnd, "UInt", 0, "UInt", 0, "UInt", 0x0101) ; RDW_UPDATENOW | RDW_INVALIDATE
  }

  ; -----------------------------------------------------------------
  ;   OnClose
  ; -----------------------------------------------------------------

  OnClose()
  {
    ExitApp
  }
  
  ; -----------------------------------------------------------------
  ;   OnEscape
  ; -----------------------------------------------------------------

  OnEscape()
  {
    this.Hide()
  }
  
  ; -----------------------------------------------------------------
  ;   Show / Hide / Destroy
  ; -----------------------------------------------------------------

  Show(options="", title="")
  {
    form_id := this.getID()
    Gui %form_id%:Show, %options%, %title% 
  }
  
  Hide()
  {
    form_id := this.getID()
    Gui %form_id%:Cancel
  }

  Destroy()
  {
    form_id := this.getID()
    Gui %form_id%:Destroy
  }

  ; -----------------------------------------------------------------
  ;   setFont
  ; -----------------------------------------------------------------

  setFont(name="", options="")
  {
    form_id := this.getID()
    Gui %form_id%:font, %options%, %name% 
  }

  ; -----------------------------------------------------------------
  ;   getID / setID
  ; -----------------------------------------------------------------

  getID()
  {
    return this._priv_.GuiName
  }

  setID(ID)
  {
    this._priv_.GuiName := ID
  }
}

